// Fill out your copyright notice in the Description page of Project Settings.


#include "PlayCharacter.h"

#include "EnemyBaseCharacter.h"
#include "MyGameInstance.h"
#include "GameFramework/GameSession.h"
#include "GameFramework/PawnMovementComponent.h"
#include "Kismet/KismetMathLibrary.h"
#include "AbilitySystemComponent.h"
#include "Ability/MeleeAttackeGameplayAbility.h"

// Sets default values
APlayCharacter::APlayCharacter()
{
	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	SpringArmComponent = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
	SpringArmComponent->bUsePawnControlRotation = true;
	SpringArmComponent->SetupAttachment(RootComponent);

	CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
	CameraComponent->SetupAttachment(SpringArmComponent);

	GetMovementComponent()->GetNavAgentPropertiesRef().bCanCrouch = true;

	AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>("AbilitySystemComponent");
}

// Called when the game starts or when spawned
void APlayCharacter::BeginPlay()
{
	Super::BeginPlay();
	// 初始化普通攻击能力
	
	AquireAbility(UMeleeAttackeGameplayAbility::StaticClass());
}

// Called every frame
void APlayCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	// 生成武器
	GenerateWeapons();
}

// Called to bind functionality to input
void APlayCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	PlayerInputComponent->BindAxis("MoveForward", this, &APlayCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &APlayCharacter::MoveRight);
	PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
	PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
	PlayerInputComponent->BindAction("Crouch", EInputEvent::IE_Pressed, this, &APlayCharacter::PlayCrouch);
	PlayerInputComponent->BindAction("CallPetWidget", EInputEvent::IE_Pressed, Cast<UMyGameInstance>(GetGameInstance()),
	                                 &UMyGameInstance::OpenPetWidget);
	PlayerInputComponent->BindAction("PetMove", EInputEvent::IE_Pressed, this, &APlayCharacter::SetPetMoveLocation);
}

void APlayCharacter::UseSkill(FSkillInfoStruct SkillInfo, UUserWidget* UW)
{
	switch (SkillInfo.SkillEnum)
	{
	case ESkillInfoEnum::FEEDING:
		FeeDingUse(SkillInfo, UW);
		break;
	case ESkillInfoEnum::CALLPET:
		CallPet(SkillInfo, UW);
		break;
	case ESkillInfoEnum::BANYUEZHAN:
		BanYueZhan();
		break;
	}
}

void APlayCharacter::FeeDingUse(FSkillInfoStruct SkillInfo, UUserWidget* UW)
{
	UMyGameInstance* inst = Cast<UMyGameInstance>(GetGameInstance());
	float cooldown = 1.f;

	GetColldown(UW, cooldown);
	if (cooldown > 0)
	{
		inst->PromptMessage(TEXT("技能冷却中"), EPromptLevel::ERROR);
		return;
	}
	if (SelectActor == nullptr)
	{
		inst->PromptMessage(TEXT("未选择喂食对象"), EPromptLevel::ERROR);
		return;
	}

	float distance = GetDistanceTo(SelectActor);
	UE_LOG(LogTemp, Log, TEXT("离目标距离 %f"), distance);
	if (distance > 500.f)
	{
		inst->PromptMessage(TEXT("距离目标太远了"), EPromptLevel::ERROR);
		return;
	}
	// 开启冷却
	EnableColldown(UW);
	const int32 randomValue = FMath::RandRange(1, 10);
	if (randomValue > 12)
	{
		inst->PromptMessage(TEXT("捕捉失败"), EPromptLevel::ERROR);
		return;
	}

	AEnemyBaseCharacter* enemyBaseCharacter = Cast<AEnemyBaseCharacter>(SelectActor);

	// 初始化宠物基类
	APetBaseCharacter* BasePetCharacter = NewObject<APetBaseCharacter>();


	//TODO 宠物资质暂时只有一种
	FString PetNickName = FString(L"普通的").Append(*enemyBaseCharacter->Name);
	BasePetCharacter->Name = PetNickName;
	BasePetCharacter->Head = enemyBaseCharacter->Head;
	BasePetCharacter->LV = 1;
	BasePetCharacter->Health = FMath::RandRange(50, 100);
	BasePetCharacter->CurrentHealth = BasePetCharacter->Health;
	BasePetCharacter->AttackPower = FMath::RandRange(100, 150);
	BasePetCharacter->Defense = FMath::RandRange(100, 150);
	BasePetCharacter->QualificationAttr = EQualification::Ordinary;
	BasePetCharacter->Favorability = 100;
	BasePetCharacter->Hunger = 100;
	BasePetCharacter->CurrentHunger = BasePetCharacter->Hunger;

	// get the blueprint class reference from the editor
	FString AnimClassStringTest = "Class'/Game/pets/Animator/ABM_Pet_Select_Lizard.ABM_Pet_Select_Lizard_C'";
	// load the class
	UClass* AnimationClass = LoadObject<UClass>(NULL, *AnimClassStringTest);

	BasePetCharacter->GetMesh()->SetAnimInstanceClass(AnimationClass);
	BasePetCharacter->GetMesh()->SkeletalMesh = enemyBaseCharacter->GetMesh()->SkeletalMesh;

	inst->AddPet(BasePetCharacter);


	const FString successTitle = *FString(L"恭喜你获得了一只").Append(PetNickName).Append(*FString(L" 请按O键打开宠物栏查看"));
	inst->PromptMessage(successTitle, EPromptLevel::SUCCESS);

	// 怪物死亡
	enemyBaseCharacter->Dead();
}

void APlayCharacter::CallPet(FSkillInfoStruct SkillInfo, UUserWidget* UW)
{
	UE_LOG(LogTemp, Log, TEXT("召唤宠物"));

	UMyGameInstance* inst = Cast<UMyGameInstance>(GetGameInstance());

	if (!fightPet)
	{
		inst->PromptMessage(TEXT("请选择出战宠物"), EPromptLevel::ERROR);
		return;
	}

	UObject* loadObj = StaticLoadObject(UBlueprint::StaticClass(), NULL,
	                                    TEXT("Blueprint'/Game/pets/Blueprints/MyPetBaseCharacter.MyPetBaseCharacter'"));
	if (loadObj != nullptr)
	{
		UBlueprint* ubp = Cast<UBlueprint>(loadObj);

		// 生成位置
		FVector localPosition = GetActorLocation() + (GetActorForwardVector() * 200);


		FRotator localRotator = FRotator(GetActorRotation().Pitch, GetActorRotation().Yaw + 180,
		                                 GetActorRotation().Roll);

		FActorSpawnParameters spawnParam;
		spawnParam.Owner = this;


		APetBaseCharacter* pet = GetWorld()->SpawnActor<APetBaseCharacter>(
			ubp->GeneratedClass, localPosition, localRotator, spawnParam);
		pet->CopyProp(fightPet);
		PetMoveLocation = FVector::Zero();
		inst->PromptMessage(TEXT("召唤成功"), EPromptLevel::SUCCESS);
	}
}

void APlayCharacter::SetPetMoveLocation()
{
	APlayerController* PlayerController = Cast<APlayerController>(GetController());
	FHitResult Hit;
	PlayerController->GetHitResultUnderCursor(ECC_Visibility, false, Hit);
	FVector ActorLocationXY = FVector(GetActorLocation().X, GetActorLocation().Y, 0);
	FVector HitLocationXY = FVector(Hit.Location.X, Hit.Location.Y, 0);
	if (UKismetMathLibrary::Vector_Distance(ActorLocationXY, HitLocationXY) < 1500)
	{
		PetMoveLocation = Hit.Location;
	}
}

UAbilitySystemComponent* APlayCharacter::GetAbilitySystemComponent() const
{
	return AbilitySystemComponent;
}

void APlayCharacter::AquireAbility(TSubclassOf<UBaseGameplayAbility> Ability)
{
	AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(Ability));
	AbilitySystemComponent->InitAbilityActorInfo(this,this);
}

void APlayCharacter::BanYueZhan()
{
	AbilitySystemComponent->TryActivateAbilityByClass(UMeleeAttackeGameplayAbility::StaticClass());
}

void APlayCharacter::MoveForward(float Value)
{
	AddMovementInput(GetActorForwardVector() * Value);
}

void APlayCharacter::MoveRight(float Value)
{
	AddMovementInput(GetActorRightVector() * Value);
}

void APlayCharacter::PlayCrouch()
{
	if (isCrouch) UnCrouch();
	else Super::Crouch();
	isCrouch = !isCrouch;
}

void APlayCharacter::GenerateWeapons()
{
}
